package com.yswy.backstage.config;

import com.yswy.backstage.annotation.NotAuth;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class ApiNotAuthContext {

    // 接口路径--方法 映射表
    public static List<String> urls = new ArrayList<>();

    private ApplicationContext applicationContext;

    /**
     * 扫描全部接口，并将其完整请求路径（不包含server.servlet.context-path）与方法的映射保存下来
     * 此方法默认所有打上@RequestMapping注解（或其派生注解）的类或方法都必须有至少一个访问路径，留空的话会抛出异常
     * @param applicationContext
     */
    public ApiNotAuthContext(ApplicationContext applicationContext) {

        this.applicationContext = applicationContext;
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(RestController.class);
        for (Map.Entry<String, Object> entry : beansWithAnnotation.entrySet()) {
            Class<?> controller = entry.getValue().getClass();
            // 获取controller上的@RequestMapping注解
            RequestMapping controllerRequestMapping = AnnotatedElementUtils.findMergedAnnotation(controller, RequestMapping.class);
            if (controllerRequestMapping != null) {
                Method[] controllerSubMethods = controller.getMethods();
                // 遍历controller下的所有方法，搜索所有加了@RequestMapping注解的方法
                for (Method method : controllerSubMethods) {
                    NotAuth notAuthMapping = AnnotatedElementUtils.findMergedAnnotation(method, NotAuth.class);
                    if (notAuthMapping == null) {
                        continue;
                    }
                    RequestMapping methodRequestionMapping = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
                    if (methodRequestionMapping == null) {
                        continue;
                    }
                    // 将controller的访问路径和method的访问路径进行拼接，并保存到一个map中
                    for (String controllerPath : controllerRequestMapping.value()) {
                        if (!controllerPath.startsWith("/")) {
                            controllerPath = "/" + controllerPath;
                        }
                        for (String methodPath : methodRequestionMapping.value()) {
                            if (!methodPath.startsWith("/")) {
                                methodPath = "/" + methodPath;
                            }
                            // API完整的请求路径
                            String fullPath = controllerPath + methodPath;
                            fullPath = fullPath.replaceAll("\\{\\w+\\}(?:/\\{\\w+\\})*", "**");
//                            System.out.println(fullPath);
                            urls.add(fullPath);
                        }
                    }
                }
            }
        }
    }
}
